home *** CD-ROM | disk | FTP | other *** search
/ Top 200 Programs / Top 200 Programs.iso / Bob8 / THOMPSON / LIBERTY / PRODUCT / TUTORIAL.EXE / WK3CM1.TXT < prev    next >
Text File  |  1996-06-06  |  13KB  |  395 lines

  1. Week 3 course material
  2. Liberty BASIC programming course
  3. Copyright 1996 Shoptalk Systems
  4. All Rights Reserved
  5.  
  6. Reading and Writing Sequential Files
  7. ==============================================================================
  8.  
  9. Now we will learn about how to work with disk files.  With few exceptions,
  10. all personal computers have at least one floppy disk drive and one hard disk
  11. drive.  Liberty BASIC provides ways to write information to disk files on
  12. these devices, and we can take advantage of this when we write our programs.
  13.  
  14. There are two ways to read and write files in Liberty BASIC.  One is called
  15. sequential and the other is called random access.  We will use the sequential
  16. method for our examples here.  The reason it is called sequential is that
  17. when reading or writing we start at the beginning of the file and work one
  18. item at a time to the end.  An item can be words or characters separated by
  19. commas, or an item can be a complete line of data.
  20.  
  21. Let's familiarize ourselves with a few Liberty BASIC statements that help us
  22. work with files.
  23.  
  24.  
  25. OPEN
  26. ------------------------------------------------------------------------------
  27.  
  28. The OPEN statement causes Liberty BASIC to open a file.  A file must be
  29. opened if we want to write into it or read from it.  There are several
  30. ways to open any file for sequential access.  These 'ways' are called modes.
  31.  
  32. The OUTPUT mode:  The OUTPUT mode is for writing to a file.  This is what an
  33. OPEN statement for OUTPUT looks like:
  34.  
  35.     open "myfile.txt" for output as #myHandle
  36.  
  37. You can see the OUTPUT mode is specified.  The last item on the line is
  38. #myHandle.  It is a name (called a file handle) given to Liberty BASIC to use
  39. for the open file.  Any code that writes to this file must include a
  40. reference to #myHandle.  This is so that Liberty BASIC knows which file to
  41. write to.
  42.  
  43. A file handle starts with a # character followed by any word or sequence of
  44. characters (using letters and digits).  It is best to choose handles that
  45. make it easy for you to remember which file you are working with while
  46. writing your program.  Some examples of valid file handles are:
  47.  
  48.     #1
  49.     #abc
  50.     #dataFile
  51.     #customers
  52.  
  53. You cannot have more than one file open at a time that uses the same file
  54. handle or your program will terminate with an error.
  55.  
  56. The INPUT mode:  There is also a mode for reading sequentially from a file.
  57. This mode is called INPUT.  Here is an example of an OPEN statement for
  58. INPUT:
  59.  
  60.     open "myfile.txt" for input as #myHandle
  61.  
  62.  
  63. CLOSE
  64. ------------------------------------------------------------------------------
  65.  
  66. The CLOSE statement is used for closing open files when we are done reading
  67. or writing them.  This is a required operation when working with files and
  68. it is a very important thing to remember when writing programs.
  69.  
  70. Here is how OPEN and CLOSE work together:
  71.  
  72.     open "myfile.txt" for output as #myHandle
  73.     'put some code in here that writes to #myHandle
  74.     close #myHandle
  75.  
  76. Another thing to remember is that a file opened for one mode must first be
  77. closed before it can be opened for a different mode.  If you are going to
  78. read from a file you've just written to, you must close the file and reopen
  79. it, like so:
  80.  
  81.     open "myfile.txt" for output as #myHandle
  82.     'put some code in here that writes to #myHandle
  83.     close #myHandle
  84.  
  85.     open "myfile.txt" for input as #myHandle
  86.     'put some code in here that reads from #myHandle
  87.     close #myHandle
  88.  
  89.  
  90. PRINT
  91. ------------------------------------------------------------------------------
  92.  
  93. We've already seen how the PRINT statement can display text into a window on
  94. the screen.  PRINT can also be used to write into a file opened for
  95. sequential OUTPUT.  Here is an example:
  96.  
  97.     open "myfile.txt" for output as #myHandle
  98.     print #myHandle, "Hello"
  99.     print #myHandle, "World!"
  100.     close #myHandle
  101.  
  102. This little program produces a file containing two lines of text (each could
  103. be considered an item, see above).  Type the code in and run it.  When the
  104. program finishes executing, open Windows Notepad on MYFILE.TXT to see the
  105. result!
  106.  
  107.  
  108. Let's Take It For A Spin
  109. ==============================================================================
  110.  
  111. Now we'll modify the AGES.BAS program from out WK2SOL.TXT file so that it
  112. saves the names and ages that we enter into a file.  Take a look at this
  113. modified program:
  114.  
  115.     'AGES.BAS
  116.     'Accept some names and ages from the user, then total and average them
  117.     dim numbers(20)
  118.     dim names$(20)
  119.     print "AGES.BAS"
  120.     print
  121.  
  122.     'loop up to 20 times, getting numbers
  123.     print "Enter up to 20 non-zero values."
  124.     print "A zero or blank entry ends the series."
  125.  
  126. [entryLoop]  'loop around until a zero entry or until index = 20
  127.  
  128.     'get the user's name and age
  129.     print "Entry "; index + 1;
  130.     input name$
  131.     if name$ = "" then [endSeries]  'quit if name$ is blank
  132.     print "Age   ";
  133.     input age
  134.  
  135.     index = index + 1       'add one to index
  136.     names$(index) = name$   'set the specified array item to be name$
  137.     numbers(index) = age    'set the specified array item to be age
  138.     total = total + age     'add entry to the total
  139.  
  140.     if index = 20 then [endSeries]  'if 20 values were entered, exit loop
  141.  
  142.     goto [entryLoop]  'go back and get another entry
  143.  
  144. [endSeries]  'entries are finished
  145.  
  146.     'Set entryCount to index
  147.     entryCount = index
  148.     if entryCount = 0 then print "No Entries." : goto [quit]
  149.  
  150.     print "Entries completed."
  151.     print
  152.     print "Here are the "; entryCount; " entries:"
  153.     print "-----------------------------"
  154.  
  155.     'This loop displays each entered value in turn.
  156.     'Notice that we re-use the index variable.  It
  157.     'can be confusing to use a new variable for each
  158.     'new loop.    
  159.     for index = 1 to entryCount
  160.       print "Entry "; index; " is "; names$(index); ", age "; numbers(index)
  161.     next index
  162.  
  163.     '*** New code starts here ***
  164.  
  165.     'Write the data into ages.dat
  166.     open "ages.dat" for output as #ages
  167.     for index = 1 to entryCount
  168.       print #ages, names$(index)
  169.       print #ages, numbers(index)
  170.     next index
  171.     close #ages
  172.  
  173.     '*** New code ends here ***
  174.  
  175.     'Now display the total and average value
  176.     print
  177.     print "The total age is "; total
  178.     print "The average age is "; total / entryCount
  179.  
  180. [quit]
  181.  
  182.     end
  183.  
  184.  
  185. Type the new program lines in.  Run the program and enter a few names and
  186. ages.  When the program finishes executing, open the file with Notepad and
  187. you'll the data you entered.  It should look something like:
  188.  
  189. Tom Jones
  190. 52
  191. Victor Krueger
  192. 39
  193. Sue White
  194. 64
  195.  
  196. Let's see how our newly added code works.
  197.  
  198. 1) First we open the file AGES.DAT with the OPEN statement.  It is opened for
  199. OUTPUT (writing) and its file handle is #ages.
  200.  
  201.     open "ages.dat" for output as #ages
  202.  
  203. 2) This sets up a FOR/NEXT loop.
  204.  
  205.     for index = 1 to entryCount
  206.  
  207. 3) Now we print a name and age, each on a separate line.
  208.  
  209.     print #ages, names$(index)
  210.     print #ages, numbers(index)
  211.  
  212. 4) Here's the back end of our FOR/NEXT loop.  Loop back until index equals
  213. entryCount.
  214.  
  215. 5) Now we will close AGES.DAT.
  216.  
  217.     close #ages
  218.  
  219.  
  220. Reading from a file
  221. ------------------------------------------------------------------------------
  222.  
  223. Now that we've written information to a disk file, we are going to read that
  224. information back into our program.  This is done using the INPUT statement.
  225. Just as we saw PRINT used to display information in a window and to write
  226. information to a disk file, INPUT can be used to get keyboard input, or to
  227. get information from a disk file.
  228.  
  229. To read from a file, it must be opened using the INPUT mode.  The OPEN
  230. statement is used like so:
  231.  
  232.     open "ages.dat" for input as #ages
  233.  
  234. Our INPUT statement for reading from a file looks a lot like the PRINT
  235. statement above:
  236.  
  237.     input #ages, var$
  238.  
  239. Notice we use the file handle, and then we specify a variable name to read
  240. into.  In a program that reads a list of items, an INPUT statement like the
  241. one above would be placed inside of a loop.  In this way each item in the
  242. file can be read in turn and stored in an array.
  243.  
  244. An important point is that that we don't always know how many items
  245. have been written to AGES.DAT.  This means we don't know when to stop looping
  246. around and reading items from the file.  One solution is to add a PRINT
  247. statement to the program that creates the file.  This PRINT statement would
  248. write the number of items at the start of the file, like so:
  249.  
  250.     'Write the data into ages.dat
  251.     open "ages.dat" for output as #ages
  252.     print #ages, entryCount
  253.     for index = 1 to entryCount
  254.       print #ages, names$(index)
  255.       print #ages, numbers(index)
  256.     next index
  257.     close #ages
  258.  
  259. Then all we would need to do is read that number first, and then loop that
  260. many times to read each name and age.  I will tackle it from a different
  261. direction though, because  I want to introduce the EOF() function.
  262.  
  263. The EOF() function stands for End Of File.  For a given file handle, it will
  264. return 0 if we are not at the end of file, and -1 if we are at the end of
  265. file.  For example:
  266.  
  267.     open "ages.dat" for input as #ages
  268.     if eof(#ages) = 0 then print "NOT AT END OF FILE"
  269.     close #ages
  270.  
  271. The above code would print NOT AT END OF FILE because we haven't read all the
  272. way to the end of the file.
  273.  
  274. Here is a version of AGES.BAS that reads it's information from the file we
  275. created above and uses EOF() to check for the end of file.
  276.  
  277.  
  278.     'AGES_IN.BAS
  279.     'Read names and ages from AGES.DAT, then total and average them.
  280.     'This version doesn't write the data back out to the file.
  281.     dim numbers(20)
  282.     dim names$(20)
  283.     print "AGES_IN.BAS"
  284.     print
  285.  
  286.     print "Reading AGES.DAT..."
  287.  
  288.     'open ages.dat
  289.     open "ages.dat" for input as #ages
  290. [entryLoop]  'loop around until end of file or until index = 20
  291.  
  292.     'test for the end of file
  293.     if eof(#ages) = -1 then [endSeries]
  294.  
  295.     'get the user's name and age
  296.     input #ages, name$
  297.     input #ages, age
  298.  
  299.     index = index + 1       'add one to index
  300.     names$(index) = name$   'set the specified array item to be name$
  301.     numbers(index) = age    'set the specified array item to be age
  302.     total = total + age     'add entry to the total
  303.  
  304.     if index = 20 then [endSeries]  'if 20 values were entered, exit loop
  305.  
  306.     goto [entryLoop]  'go back and get another entry
  307.  
  308. [endSeries]  'entries are finished
  309.  
  310.     'close ages.dat
  311.     close #ages
  312.  
  313.     'Set entryCount to index
  314.     entryCount = index
  315.     if entryCount = 0 then print "No Entries." : goto [quit]
  316.  
  317.     print "Entries completed."
  318.     print
  319.     print "Here are the "; entryCount; " entries:"
  320.     print "-----------------------------"
  321.  
  322.     'This loop displays each entered value in turn.
  323.     'Notice that we re-use the index variable.  It
  324.     'can be confusing to use a new variable for each
  325.     'new loop.    
  326.     for index = 1 to entryCount
  327.       print "Entry "; index; " is "; names$(index); ", age "; numbers(index)
  328.     next index
  329.  
  330.     'Now display the total and average value
  331.     print
  332.     print "The total age is "; total
  333.     print "The average age is "; total / entryCount
  334.  
  335. [quit]
  336.  
  337.     end
  338.  
  339.  
  340.  
  341. Challenge Exercise
  342. ------------------------------------------------------------------------------
  343.  
  344. Create a modified ARRAYS.BAS using the code below so that it keeps its list
  345. in a disk file named ARRAYS.DAT.  The program must read its list from
  346. ARRAYS.DAT before asking for additional names.  When the user is done
  347. entering names, or if all the slots are filled, the list will be written to
  348. ARRAYS.DAT before the program ends.  See the source code below for some
  349. clues.
  350.  
  351.  
  352.     'ARRAYS2.BAS
  353.     'List handling with arrays and file input/output.
  354.     'This version stores more than 10 names.
  355.  
  356.     dim names$(50)  'set up our array to contain 50 items
  357.  
  358.     'Insert code that reads ARRAYS.DAT into the array names$.
  359.  
  360. [askForName]  'ask for a name
  361.     input "Please give me your name ?"; yourName$
  362.     if yourName$ = "" then print "No name entered." : goto [quit]
  363.  
  364.     index = 0
  365. [insertLoop]
  366.     'check to see if index points to an unused item in the array
  367.     if names$(index) = "" then names$(index) = yourName$ : goto [nameAdded]
  368.     index = index + 1 'add 1 to index
  369.     if index < 50 then [insertLoop] 'loop back until we have counted to 50
  370.  
  371.     'There weren't any available slots, inform user
  372.     print "All ten name slots already used!"
  373.     goto [quit]
  374.  
  375. [nameAdded]  'Notify the name add was successful
  376.  
  377.     print yourName$; " has been added to the list."
  378.     goto [askForName]
  379.  
  380. [quit]
  381.  
  382.     'display all the entered names
  383.     print
  384.     print "Here is a list of the names entered:"
  385.     print "------------------------------------"
  386.  
  387.     for index = 0 to 49
  388.         if names$(index) <> "" then print names$(index)
  389.     next index
  390.  
  391.     'Insert code that saves the names$ array to ARRAYS.DAT.
  392.  
  393.     end
  394.  
  395.